package com.ui.basic.interceptor;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.jsecurity.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.support.RequestContextUtils;

import com.common.basic.util.Globals;
import com.ui.basic.command.CommandMenu;
import com.ui.basic.dao.assembler.MenuAssembler;
import com.ui.basic.ibatis.dao.system.TblSMenuDAO;
import com.ui.basic.ibatis.model.system.TblSMenuExample;
import com.ui.basic.resolver.MessageResolver;

@Service("menuInterceptor")
@Repository
public class MenuInterceptor implements HandlerInterceptor {
	private static final transient org.apache.commons.logging.Log LOGGER = org.apache.commons.logging.LogFactory
			.getLog(MenuInterceptor.class);

	@Autowired
	private MessageResolver messageResolver;
	@Autowired
	private TblSMenuDAO menuDAO;
	@Autowired
	private MenuAssembler menuAssembler;

	public void afterCompletion(HttpServletRequest arg0,
			HttpServletResponse arg1, Object arg2, Exception arg3)
			throws Exception {
		LOGGER.debug(">>>>MenuInterceptor.afterCompletion");
	}

	public void postHandle(HttpServletRequest request,
			HttpServletResponse response, Object object, ModelAndView view)
			throws Exception {
		LOGGER.debug(">>>>MenuInterceptor.postHandle");
		Boolean errorReq = (Boolean) request
				.getAttribute(Globals.ERROR_REQUESTED_LINK);
		if (request.getMethod().equalsIgnoreCase("GET") 
				&& errorReq != null && !errorReq.booleanValue()
				&& request.getSession()!=null) {
			view.setViewName("login");
		}
	}

	@SuppressWarnings("unchecked")
	public boolean preHandle(HttpServletRequest req, HttpServletResponse resp,
			Object arg2) throws Exception {
		LOGGER.debug(">>>>MenuInterceptor.preHandle");
		boolean blnProcessReq = true;
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) resp;
		
		messageResolver.setLocale(RequestContextUtils.getLocale(request));
		menuAssembler.setMessageResolver(messageResolver);

		List<CommandMenu> listMenu = null;

		// get menu link user requested
		int intUserReq = (request.getRequestURI()).indexOf(request
				.getServletPath()
				+ "/");
		String strUserReq = (request.getRequestURI()).substring(intUserReq);
		LOGGER.debug("***********strUserReq == " + strUserReq);

		if (!strUserReq.equalsIgnoreCase(messageResolver
				.getMessage("app.url.login"))
				&& !strUserReq.equalsIgnoreCase(messageResolver
						.getMessage("app.url.captcha"))
				&& !SecurityUtils.getSubject().isAuthenticated()) {
			LOGGER.debug("NOT LOGIN YET");
			if(request.getMethod().equalsIgnoreCase("GET")){
				if(request.getSession()==null){
					sendError(response, messageResolver.getMessage("error.sessionTimeout"));
					return false;
				}
				request.getRequestDispatcher(messageResolver.getMessage("app.url.login")).forward(req,resp);
			}else{
				sendError(response, messageResolver.getMessage("error.sessionTimeout"));
				return false;
			}
		}

		TblSMenuExample example = new TblSMenuExample();
		example.setOrderByClause("MENU_CODE");
		List listTblMenu = menuDAO.selectByExample(example);
		request.setAttribute(Globals.ARR_MENU_CODE, menuAssembler.getStringMenuView(listTblMenu));
		LOGGER.debug(">>>ARR_MENU_CODE == " + request.getAttribute(Globals.ARR_MENU_CODE));
		// *****check non static menu
		if (!strUserReq.equalsIgnoreCase(messageResolver
				.getMessage("app.url.login"))
				&& !strUserReq.equalsIgnoreCase(messageResolver
						.getMessage("app.url.captcha"))
				&& !strUserReq.equalsIgnoreCase(messageResolver
						.getMessage("app.url.logout"))
				&& !strUserReq.equalsIgnoreCase(messageResolver
						.getMessage("app.url.renderMenu"))
				&& !strUserReq.equalsIgnoreCase(messageResolver
						.getMessage("app.url.home"))) {
			blnProcessReq = menuAssembler.validateLinkRequest(listTblMenu, strUserReq);
			Boolean prBoolean = Boolean.valueOf(blnProcessReq);
			request.setAttribute(Globals.ERROR_REQUESTED_LINK, prBoolean);
			SecurityUtils.getSubject().getSession().setAttribute(Globals.ERROR_REQUESTED_LINK, prBoolean);
			request.setAttribute(Globals.USER_KEY, menuAssembler.getUserFromJSecurity());
			LOGGER.debug("*****validateLinkRequest == " + blnProcessReq);
		}

		// ***render menu viewable
		if(strUserReq.equalsIgnoreCase(messageResolver.getMessage("app.url.renderMenu")) 
				|| request.getMethod().equalsIgnoreCase("GET")){
			if (!strUserReq.equalsIgnoreCase(messageResolver
					.getMessage("app.url.login"))
					&& !strUserReq.equalsIgnoreCase(messageResolver
							.getMessage("app.url.captcha"))
					&& !strUserReq.equalsIgnoreCase(messageResolver
							.getMessage("app.url.logout"))) {
				listMenu = menuAssembler.toDtoList(listTblMenu);
			}
			if (listMenu != null && listMenu.size() > 0) {
				CommandMenu menu = listMenu.get(listMenu.size() - 1);
				int idx = menu.getPrefix().indexOf("_");
				int nummenu = 0;
				if (idx == -1)
					nummenu = Integer.parseInt(menu.getPrefix());
				else
					nummenu = Integer.parseInt(menu.getPrefix().substring(0, idx));

				request.setAttribute("usermenu.nummenu", Integer.valueOf(nummenu));
				request.setAttribute("usermenu.listmenu", listMenu);
			}
		}
		
		response.addHeader("Cache-Control", "no-cache");

		return true;
	}

	public void setMenuDAO(TblSMenuDAO menuDAO){
		this.menuDAO = menuDAO;
	}

	public void setMenuAssembler(MenuAssembler menuAssembler) {
		this.menuAssembler = menuAssembler;
	}

	public void setMessageResolver(MessageResolver messageResolver) {
		this.messageResolver = messageResolver;
	}

	protected void sendError(HttpServletResponse response, String msg){
		LOGGER.debug(">>>>MenuInterceptor.sendError");
		try{
			PrintWriter out = response.getWriter();
			out.println("[error]:"+msg);
			out.flush();
			out.close();
		}catch(IOException ioe){}
	}

}